<?php
declare (strict_types=1);

namespace app\wxApi\controller;

set_time_limit(0);

use Ali\OSS\OSS;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\facade\Db;
use think\Request;
use think\facade\Cache;
use Overtrue\Pinyin\Pinyin;
class Script
{
    /**
     * @throws Exception
     */
    public function uploadFilesToOSS(): void
    {
        try {
            // Cache::clear('script_sign');
            $sign =Cache::get('script_sign');
            if(!empty($sign)){
                writeLogToDb('上次任务未执行完成',1,0,['time'=>date('Y-m-d H:i:s')]);
            }

            Cache::set('script_sign',true);
            $oss = new OSS();
            $condition = [
                ['video_local_url', '<>', 'null'],
                ['video_status', '=', '1']
            ];
            $data = Db::name('answer')->alias('answer')
                ->join('examinee_baseinfo baseinfo','answer.examinee_id=baseinfo.id')
                ->join('active','answer.active_id=active.id')
                ->field(['answer.id','video_local_url','answer.type','level','baseinfo.name','active.code'])
                ->where($condition)->select()->toArray();
            // print_r($data);
            // exit;
            if(count($data)==0){
                throw new Exception('脚本记录:本次没有可执行的任务',0);
            }
            // dump(Db::getLastSql());
            // 遍历数据
            foreach ($data as $item) {
                $url = root_path().'public/'.$item['video_local_url'];
                if (!file_exists($url)) {
//                    throw new Exception('脚本报错:要上传的文件不存在:url:'.$url);
                    writeLogToDb('文件不存在', 1, 0, $url);
                    continue;
                }
                // 创建 Pinyin 实例
                $pinyin = new Pinyin();
                $rename = $pinyin->permalink($item['name'],'');
                $rename.=$item['type']==2?'_direct':'_recite';
                $rename.= '_lv'.$item['level'];
                $upload = $oss->fragment(basename($url), $url, 'examinee/video/'.$item['code'].'/',false,$rename);
                // dump($upload);
                if(isset($upload['info']['url'])&&!empty($upload['info']['url'])){
                    $parts = parse_url($upload['info']['url']);
                    // 构造问号前的部分
                    $video_oss_url = $parts['scheme'] . '://' . $parts['host'];

                    if (isset($parts['port'])) {
                        $video_oss_url .= ':' . $parts['port'];
                    }

                    $video_oss_url .= $parts['path'];
                    $updateData= [
                        'id'=>$item['id'],
                        'video_url'=>str_replace("-internal", "", $video_oss_url),
                        'video_status'=>2
                    ];
                    $updateResult = Db::name('answer')->save($updateData);
                    // print_r(Db::getLastSql());
                    if($updateResult!==false){
                        @unlink($url);
                        writeLogToDb('脚本记录:文件上传成功',1,0,['id'=>$item['id'],'url'=>$url,'ossUrl'=>$video_oss_url]);
                    }
                }
                Cache::set('script_sign',null);
                writeLogToDb('脚本记录:上传文件有结果', 1, 0, $upload);
            }
        } catch (DataNotFoundException|ModelNotFoundException|DbException $e) {
            if($e->getCode()==0){
                writeLogToDb( $e->getMessage(), 1, 0, $e->getMessage());
            }else{
                writeLogToDb('脚本报错:', 1, 0, $e->getMessage());
            }

        }
    }

    /**
     * 调用压缩oss 上的目录文件夹
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function compressOssFiles(): void
    {
        $condition = [
            ['zip_url', '=', null],
            ['end_time', '<', date('Y-m-d') . ' 00:00:01']
        ];
        // 查询出已经结束并且压缩文件地址为null的考试信息
        $active = Db::name('active')->where($condition)->select()->toArray();

        if (count($active) == 0) {
            writeLogToDb('没有需要压缩的申报信息', 1, 1, []);
            die();
        }
        foreach ($active as $item) {
            $fileInfo = [
                "bucket" => "cdfherp",
                "source-dir" => "examinee/video/".$item['code'].'/',
            ];
            $result=$this->sendCurl(json_encode($fileInfo));
            if($result===false){
                writeLogToDb('创建压缩文件失败',1,1,['data'=>$item]);
                continue;
            }
            $zipUrl = "https://cdfherp.oss-cn-beijing.aliyuncs.com/output/".$result['requestId'].'.zip';
            $update = Db::name('active')->update(['zip_url'=>$zipUrl,'id'=>$item['id']]);
            if($update!==false){
                writeLogToDb('视频文件压缩成功',1,1,['url'=>$zipUrl,'data'=>$item]);
            }else{
                writeLogToDb('视频文件压缩失败',1,1,['data'=>$item]);
            }
        }
        die();
    }

    /**
     * curl请求阿里云oss地址
     * @param $json
     * @return false|mixed|void
     */
    private  function  sendCurl($json){
        $ch = curl_init();

        // 设置 cURL 选项
        curl_setopt($ch, CURLOPT_URL, "https://zip-ossunc-ykoc-bjjxwjcfjf.cn-beijing.fcapp.run");
        curl_setopt($ch, CURLOPT_HEADER, 0); // 不需要响应头
        curl_setopt($ch, CURLOPT_NOPROGRESS, true); // 不需要进度回调函数
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 跟随重定向

        curl_setopt($ch, CURLOPT_POST, true); // 发送 POST 请求
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);// 设置返回结果为字符串，而非直接输出
        curl_setopt($ch, CURLOPT_POSTFIELDS, $json); // POST 数据

        // 执行 cURL 请求
        $response = curl_exec($ch);
        curl_close($ch);
        // 检查是否有错误发生
        if (curl_errno($ch)) {
            echo 'cURL error:' . curl_error($ch);
        } else {
            // 请求成功，获取响应码
            $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            if ($httpStatusCode == 200) {
                return  json_decode(json_decode($response,true),true);
            } else {
                return  false;
            }
        }
    }
}
